/**
 *                         _ooOoo_
 *                        o8888888o
 *                        88" . "88
 *                        (| -_- |)
 *                         O\ = /O
 *                     ____/`---'\____
 *                   .   ' \| |// `.
 *                    / \||| : |||// \
 *                  / _||||| -:- |||||- \
 *                    | | \\\ - /// | |
 *                  | \_| ''\---/'' | |
 *                   \ .-\__ `-` ___/-. /
 *                ___`. .' /--.--\ `. . __
 *             ."" '< `.___\_<|>_/___.' >'"".
 *            | | : `- \`.;`\ - /`;.`/ - ` : | |
 *              \ \ `-. \_ __\ /__ _/ .-` / /
 *      ======`-.____`-.___\_____/___.-`____.'======
 *                         `=---='
 * 
 * .....................................................
 *              佛祖保佑            永无BUG
 * 
 */

$(function() {
    // 游戏状态
    var gameState = false

    // 玩家
    var player = null

    // 游戏窗口大小
    var WINDOW_WIDTH = 900 * 0.95
    var WINDOW_HEIGHT = 600 * 0.8

    // 游戏时间
    var gameTime = 0

    // 定时器
    var enemiesInterval = null
    var lightInterval = null
    var planetInterval = null
    var gameTimeInterval = null

    // 帧
    var FPS = 120

    // BGM
    var bgm = $('#bgm')[0]
    var bgmState = false

    // 排行榜数据
    var rank = []

    var enemies = []

    class Player {
        constructor() {
            // 玩家图片
            this.imgs = 'images/seven.png'
            this.width = 33
            this.height = 28

            // 速度
            this.speed = 2

            // 光上限
            this.lightMax = 100

            // 发射子弹音效
            this.shootSoundUrl = 'sound/jiaosheng.mp3'

            this.init()
        }
        init() {
            // 位置
            this.x = 20
            this.y = (600 * 0.8 - this.height) / 2

            // 得分
            this.score = 0

            // 游戏时间
            this.gameTime = 0

            // 能量余量
            this.light = this.lightMax

            // 向页面中添加节点
            this.dom = $(`<div class="player"></div>`)[0]
            this.dom.style.width = this.width + 'px'
            this.dom.style.height = this.height + 'px'
            this.dom.style.background = `url(${this.imgs}) no-repeat`
            this.dom.style.backgroundPosition = '-36px 0px'

            this.keyState = [false, false, false, false]

            $('.game-frame')[0].append(this.dom)

            this.dom.style.top = this.y + 'px'
            setTimeout(() => {
                this.dom.style.left = this.x + 'px'
            }, 500)

            // 逐帧刷新
            this.interval = setInterval(() => {
                this.x += (this.keyState[0] * (-1) + this.keyState[2]) * this.speed
                this.y += (this.keyState[1] + this.keyState[3] * (-1)) * this.speed
                if (this.x < 0) this.x = 0
                if (this.y < 0) this.y = 0
                if (this.x > (WINDOW_WIDTH - this.width)) this.x = WINDOW_WIDTH - this.width
                if (this.y > (WINDOW_HEIGHT - this.height)) this.y = WINDOW_HEIGHT - this.height
                this.dom.style.left = this.x + 'px'
                this.dom.style.top = this.y + 'px'
                this.collide()

                // 删除子弹
                for (const i in this.bullets) {
                    if (this.bullets.hasOwnProperty(i)) {
                        const bullet = this.bullets[i];
                        if (bullet.x < 0 || bullet.x > WINDOW_WIDTH) {}
                    }
                }

                // 设置进度条
                $('#light-progress-content')[0].style.width = (this.light / this.lightMax) * 100 + '%'
            }, 1000 / FPS)
        }

        shoot() {
            if (!gameState || this.light < 1) return

            // 音效加载
            $('#shoot-sound')[0].play()
            $('#shoot-sound')[0].volume = 1

            new PlayerBullet({
                top: this.y,
                left: this.x + this.width * 0.75
            })
            this.light--
        }
        getScore() {
            if (!gameState) return
            this.score++
                $('#score')[0].innerHTML = this.score
        }
        getLight() {
            if (!gameState) return

            if (this.light < this.lightMax - 10) {
                this.light += 10
                return
            }
            this.light = this.lightMax
        }
        collide() {
            if (!gameState) return

            for (const i in enemies) {
                const enemy = enemies[i];
                if (this.x < enemy.x + enemy.width &&
                    this.x + this.width > enemy.x &&
                    this.y < enemy.y + enemy.height &&
                    this.height + this.y > enemy.y) {
                    enemies.splice(i, 1)
                    this.die()
                    enemy.die(true)
                }
            }
        }
        die() {
            window.clearInterval(this.interval)
            this.dom.remove()
            gameover()
        }
    }

    class PlayerBullet {
        constructor(position) {
            this.speed = 4
            this.x = position.left
            this.y = position.top
            this.img = 'images/bullet.png'
            this.width = 32
            this.height = 18
            this.init()
        }
        init() {
            this.dom = $(`<div class="bullet"></div>`)[0]
            this.dom.style.top = this.y + 'px'
            this.dom.style.left = this.x + 'px'
            this.dom.style.width = this.width + 'px'
            this.dom.style.height = this.height + 'px'
            this.dom.style.background = `url(${this.img}) no-repeat`
            $('.game-frame')[0].append(this.dom)

            this.interval = setInterval(() => {
                if (!gameState) window.clearInterval(this.interval)
                this.x += this.speed
                this.dom.style.left = this.x + 'px'
                this.collide()
                    // 超出屏幕删除节点
                if (this.x > WINDOW_WIDTH) this.die()
            }, 1000 / FPS)
        }
        die() {
            window.clearInterval(this.interval)
            this.dom.remove()
        }
        collide() {
            for (const i in enemies) {
                const enemy = enemies[i];
                if (this.x < enemy.x + enemy.width &&
                    this.x + this.width > enemy.x &&
                    this.y < enemy.y + enemy.height &&
                    this.height + this.y > enemy.y) {
                    enemies.splice(i, 1)
                    this.die()
                    enemy.die(true)
                    player.getScore()
                }
            }
        }
    }

    class Enemy {
        constructor() {
            const imgs = ['images/ship_1.png', 'images/ship_3.png']
            this.img = imgs[Math.floor(Math.random() * imgs.length)]
            this.explodeImg = 'images/explode/e1.gif'
            this.width = 32
            this.height = (68 / 76) * this.width
            this.x = WINDOW_WIDTH - this.width
            this.y = Math.random() * (WINDOW_HEIGHT - this.height)
            this.speed = 1
            this.dieState = false
            this.init()
        }
        init() {
            this.dom = $(`<div class="enemy"></div>`)[0]
            this.dom.style.width = this.width + 'px'
            this.dom.style.height = this.height + 'px'
            this.dom.style.top = this.y + 'px'
            this.dom.style.left = this.x + 'px'
            this.dom.style.background = `url(${this.img}) no-repeat`
            this.dom.style.backgroundPosition = '3px 0px'
            this.dom.style.backgroundSize = 'cover'

            this.enemyAnimation()
            $('.game-frame')[0].append(this.dom)

            this.moveInterval = setInterval(() => {
                if (!gameState) window.clearInterval(this.moveInterval)
                this.x -= this.speed
                this.dom.style.left = this.x + 'px'
                if (this.x < -this.width) this.die()
            }, 1000 / FPS);
        }
        enemyAnimation() {
            let a = 0
            this.aniInterval = setInterval(() => {
                let localLeft = [2, -27, -55, -84]
                this.dom.style.backgroundPosition = localLeft[a % 4] + 'px 0px'
                a++
            }, 1000 / 4);
        }
        die(boo) {
            if (this.dieState) return
            this.dieState = true
            window.clearInterval(this.moveInterval)
            window.clearInterval(this.aniInterval)
            this.dom.remove()
            if (boo) {
                let a = 1
                let e = $(`<div class="explode"></div>`)[0]
                $('#destroyed-sound')[0].load()
                $('#destroyed-sound')[0].play()
                $('#destroyed-sound')[0].volume = 0.5
                e.style.width = (this.width + 5) + 'px'
                e.style.height = (this.width + 5) * 100 / 71 + 'px'
                e.style.background = 'url(images/explode/e' + a + '.gif) center no-repeat'
                e.style.backgroundSize = 'cover'
                e.style.left = this.x + 'px'
                e.style.top = this.y + 'px'
                $('.game-frame')[0].append(e)
                this.explodeInterval = setInterval(() => {
                    if (a > 16) {
                        window.clearInterval(this.explodeInterval)
                        e.remove()
                    }
                    e.style.background = 'url(images/explode/e' + a + '.gif) center no-repeat'
                    a++
                }, 1000 / 20);
            }
        }
    }

    class Light {
        constructor() {
            this.img = 'images/light.png'
            this.size = 30
            this.x = Math.random() * (WINDOW_WIDTH - this.size)
            this.y = -this.size
            this.init()
        }
        init() {
            this.dom = $(`<img src="${this.img}" alt="light" class="light">`)[0]
            this.dom.style.width = this.size + 'px'
            this.dom.style.height = this.size + 'px'
            this.dom.style.top = this.y + 'px'
            this.dom.style.left = this.x + 'px'
            $('.game-frame')[0].append(this.dom)
            this.interval = setInterval(() => {
                if (!gameState) window.clearInterval(this.interval)
                this.y += 1

                this.dom.style.top = this.y + 'px'

                this.collide()
                if (this.y > WINDOW_HEIGHT) this.die()
            }, 1000 / FPS);
        }
        die() {
            window.clearInterval(this.interval)
            this.dom.remove()
        }
        collide() {
            if (!gameState) return
            if (this.x < player.x + player.width &&
                this.x + this.size > player.x &&
                this.y < player.y + player.height &&
                this.size + this.y > player.y) {
                this.die()
                player.getLight()
            }
        }
    }

    class Planet {
        constructor() {
            let imgs = ['images/planets/001-global.png', 'images/planets/002-travel.png', 'images/planets/003-science-2.png', 'images/planets/004-science-1.png', 'images/planets/005-science.png', 'images/planets/006-mars.png', 'images/planets/007-planet-earth-1.png', 'images/planets/008-earth-globe.png', 'images/planets/009-saturn.png', 'images/planets/010-uranus.png', 'images/planets/011-planet-earth.png', 'images/planets/012-jupiter.png']
            this.img = imgs[Math.floor(Math.random() * imgs.length)]
            this.speed = 1
            this.size = Math.random() * 60 + 20
            this.x = WINDOW_WIDTH
            this.y = Math.random() * (WINDOW_HEIGHT - this.size)
            this.init()
        }
        init() {
            this.dom = $(`<img src="${this.img}" alt="planet" class="planet">`)[0]
            this.dom.style.width = this.size + 'px'
            this.dom.style.height = this.size + 'px'
            this.dom.style.left = this.x + 'px'
            this.dom.style.top = this.y + 'px'
            $('.game-frame')[0].append(this.dom)
            this.interval = setInterval(() => {
                if (!gameState) window.clearInterval(this.interval)

                this.x -= this.speed

                this.dom.style.left = this.x + 'px'

                if (this.x < -this.size) this.die()
            }, 1000 / FPS);
        }
        die() {
            window.clearInterval(this.interval)
            this.dom.remove()
        }
    }

    function addLinster(p) {
        // 键盘状态
        window.addEventListener('keydown', (e) => {
            if (!gameState) return
            switch (e.keyCode) {
                case 87:
                case 38:
                    p.keyState[3] = true
                    break;
                case 68:
                case 39:
                    p.keyState[2] = true
                    break
                case 83:
                case 40:
                    p.keyState[1] = true
                    break
                case 65:
                case 37:
                    p.keyState[0] = true
                    break
            }
        })
        window.addEventListener('keyup', (e) => {
            if (!gameState) return
            switch (e.keyCode) {
                case 87:
                case 38:
                    p.keyState[3] = false
                    break;
                case 68:
                case 39:
                    p.keyState[2] = false
                    break
                case 83:
                case 40:
                    p.keyState[1] = false
                    break
                case 65:
                case 37:
                    p.keyState[0] = false
            }
        })
        window.addEventListener('keypress', (e) => {
            if (!gameState) return
            if (e.keyCode == 32) p.shoot()
        })
    }

    // 页面初始化
    $(document).ready(() => {
        if (gameTime) gameTime = 0
        if (gameTimeInterval) window.clearInterval(gameTimeInterval)
        if (enemiesInterval) window.clearInterval(enemiesInterval)
        if (lightInterval) window.clearInterval(lightInterval)
        if (planetInterval) window.clearInterval(planetInterval)
        $('#game-explain').addClass('game-explain-show')
    })


    // 开始游戏
    $('.game-start-btn').click(() => {
        $('#game-explain').removeClass('game-explain-show')
        gameInit()
    });

    function gameInit() {
        if (!gameState) gameState = true
            // 清除残留数据
        for (const i in enemies) {
            if (enemies.hasOwnProperty(i)) {
                const enemy = enemies[i];
                enemy.die()
            }
        }
        enemies = []
        player = null
        try {
            $('#game-over').removeClass('game-over-show')
            $('#rank')[0].style.height = '0'
            $('#rank-content').children().remove()
        } catch (error) {
            console.log(error)
        }


        // 战歌起
        bgm.play()
        bgm.volume = 0.1
        bgmState = true
        $('.sound-switch').click(() => {
            if (bgmState) {
                bgm.pause()
                bgmState = false
            } else {
                bgm.play()
                bgmState = true
            }
        })

        // ウルトラマンセブン参上
        player = new Player()
        addLinster(player)

        // 一大波外星人即将来袭
        enemiesInterval = setInterval(() => {
            enemies.push(new Enemy())
        }, 1 * 1000);

        lightInterval = setInterval(() => {
            new Light()
        }, 6 * 1000);

        planetInterval = setInterval(() => {
            new Planet()
        }, 1 * 1000);

        gameTimeInterval = setInterval(() => {
            gameTime++
            $('#count-down')[0].innerHTML = gameTime
        }, 1000);
    }

    function gameover() {
        gameState = false
        window.clearInterval(enemiesInterval)
        window.clearInterval(gameTimeInterval)
        window.clearInterval(lightInterval)
        window.clearInterval(planetInterval)
        bgm.pause()
        bgm.load()
        $('#game-over').addClass('game-over-show')
    }

    function rankSort(arr) {
        var max = arr.length - 1;
        for (var j = 0; j < max; j++) {
            // 声明一个变量，作为标志位
            var done = true;
            for (var i = 0; i < max - j; i++) {
                if (arr[i].score < arr[i + 1].score) {
                    var temp = arr[i];
                    arr[i] = arr[i + 1];
                    arr[i + 1] = temp;
                    done = false;
                }
            }
            if (done) {
                break;
            }
        }
        return arr;
    }

    $('.gameover-btn').click(() => {
        let val = $('#player-name').val()
        if (val) {
            rank = JSON.parse(localStorage.getItem('rank')) || []
            let a = {
                name: val,
                score: player.score,
                time: gameTime
            }
            rank.push(a)
            console.log(rank)
                // rank排序
            rank = rankSort(rank)
            console.log(rank)
            localStorage.setItem('rank', JSON.stringify(rank))
            $('#rank')[0].style.height = '100%'
            for (const i in rank) {
                if (rank.hasOwnProperty(i)) {
                    const rankItem = rank[i];
                    const tr = $('<tr></tr>')
                    const td1 = $(`<td>${(Number(i)+1)}</td>`)
                    const td2 = $(`<td>${rankItem.name}</td>`)
                    const td3 = $(`<td>${rankItem.time}</td>`)
                    const td4 = $(`<td>${rankItem.score}</td>`)
                    tr.append(td1)
                    tr.append(td2)
                    tr.append(td3)
                    tr.append(td4)
                    $('#rank-content').append(tr)
                }
            }
        }
    })

    $('.game-restart-btn').click(() => {
        window.location.reload()
    })
})